import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import AudioMedia from '@/components/AudioMedia';
import { sendCustomeizeMessage, renderStream } from '@/utils/lib';
import { launchFullScreen, fullscreenEnabled, cancelFullScreen, dataURItoBlob } from '@/utils';
import VideoTool, { ToolPrpos } from './VideoTool';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '@/store';
import { StreamListProps, setRenderedStream } from '@/store/reducers/stream';
import DescMask from '@/components/DescMask';
import Message from '@/utils/message';
import Instructions from './Instructions';
import { ReceiveBroadcastMap, useBusiness } from '../Context/BusinessContext';
import { IBusiness } from '../Context/BusinessContext';
import CustomerCanvas from './CustomerCanvas';
import { useStream } from '../Context/StreamContext';

import { ignoreBusiness, IBusinessStatus } from '../Context/BusinessContext';
import useSyncState from '../hooks/useSyncState';
import styled from '@emotion/styled';
import { useTranslation } from 'react-i18next';
import AgentService, { IEvent, ILayout, Video } from '@/modules/Agent';
import MediaStatus from '@/modules/media-status/MediaStatus';
import { resizeWin } from '@/utils/resize';
import { message } from 'antd';
import AuthorizationTips from './AuthorizationTips';
import { update } from 'lodash';
// import { createCustomerStreamContainer } from '../CustomerStreamMark';
import { IBusinessName } from '@/modules/interface';
import { uploadFileWithBlob } from '@/api';
interface CustomerStreamProps {
	layout?: string;
	width?: string;
	height?: string;
	callMediaType: string;
}

const RenderErrorMessage = styled.span`
	display: inline-block;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	font-size: 16px;
	color: #fff;
`;

const LargeVideoWrapper = styled.div`
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
`;

const InstructionsSpan = styled.span`
	color: #d7d7d7;
	font-family: simsun;
	display: inline-block;
	width: 1.5em;
	vertical-align: bottom;
	overflow: hidden;
	animation: dot 3s infinite step-start;
	@keyframes dot {
		0% {
			width: 0;
			margin-right: 1.5em;
		}
		33% {
			width: 0.5em;
			margin-right: 1em;
		}
		66% {
			width: 1em;
			margin-right: 0.5em;
		}
		100% {
			width: 1.5em;
			margin-right: 0;
		}
	}
`;

const NetWork = styled.div`
	position: absolute;
	color: #fff;
	z-index: 2;
	right: 0;
	bottom: 0;
`;

const defaultTools = [
	{
		id: 1,
		icon: 'icon-widget-shengyinkai',
		text: '',
		isActive: false,
		activeIcon: 'icon-widget-shengyinguan',
		mode: 'unmute'
	},
	{
		id: 2,
		icon: 'icon-widget-a-bianzu19',
		text: '',
		isActive: false,
		activeIcon: 'icon-widget-a-bianzu421',
		mode: 'update'
	},
	{
		id: 3,
		icon: 'icon-widget-quanping3',
		text: '',
		isActive: false,
		activeIcon: 'icon-widget-suoxiao',
		mode: 'scale'
	},
	{
		id: 4,
		icon: 'icon-widget-huazhonghua',
		text: '',
		isActive: false,
		activeIcon: 'icon-widget-huazhonghua',
		mode: 'picture'
	},
	{
		id: 5,
		icon: 'icon-widget-a-jietu2',
		text: '',
		isActive: false,
		activeIcon: 'icon-widget-a-jietu2',
		mode: 'screenshot'
	}
	// {
	// 	id: 5,
	// 	icon: 'icon-widget-biaozhu',
	// 	text: '',
	// 	isActive: false,
	// 	activeIcon: 'icon-widget-biaozhu',
	// 	mode: 'mark'
	// }
];

const CustomerStream = (props: CustomerStreamProps) => {
	const { t } = useTranslation();
	const { layout, width, height, callMediaType } = props;
	const { renderedStreams, networkStatus } = useSelector((state: RootState) => state);
	const { largeStream, getAudioLevel, recordPoint } = useStream();
	const [customerName, setCustomerName] = useState<string>('');

	const [customerRole, setCustomerRole] = useState<string>('');

	const { BusinessTaskMap, business, setBusiness } = useBusiness();

	const [businessData, setBusinessData] = useState<any>(null);

	const [audioLevel, setAudioLevel] = useSyncState<number>(0);

	const [renderErrorMessage, setRenderErrorMessage] = useSyncState<boolean>(false);

	const [tools, setTools] = useState<ToolPrpos[]>(defaultTools);

	const [mediaStatus, setMediaStatus] = useState<{ status: string; notGood: boolean }>({ status: '', notGood: false });
	const [ccsStatus, setCcsStatus] = useState<{ status: string }>({ status: 'connected' });

	const getBusiness = () => {
		if (largeStream()[0] && largeStream()[0].clientId) {
			let broadcastData = ReceiveBroadcastMap.get(largeStream()[0].clientId);
			let data = BusinessTaskMap.getTask(largeStream()[0].clientId) || broadcastData?.data.content;
			if (data && ignoreBusiness.indexOf(data.name) <= -1) {
				return data;
			}
		}
	};

	useEffect(() => {
		MediaStatus.addRenderMediaStatusEventLinstener((data: any) => {
			if (!data) {
				return;
			}
			const items = data.filter((item: any) => item.streamLabel === largeStream()[0]?.label);

			if (items && items.length > 0) {
				setMediaStatus({ status: items[0].status, notGood: items[0].notGood });
			}
		});
		AgentService.addEventListener(resp => {
			if (resp.event === IEvent.PICTURE_IN_PICTURE) {
				if (resp.data.status === 'success' && resp.data.data.mode === 'entry') {
					const list = [...tools];
					list.forEach((item: ToolPrpos) => {
						if (item.mode === 'picture') {
							item.isActive = true;
						}
					});
					setTools([...list]);
				}
				if (resp.data.status === 'success' && resp.data.data.mode === 'exit') {
					const list = [...tools];
					list.forEach((item: ToolPrpos) => {
						if (item.mode === 'picture') {
							item.isActive = false;
						}
					});
					setTools([...list]);
				}
				if (resp.data.status === 'error' && resp.data.data.mode === 'entry') {
					message.warning(t('pip-not-support'));
				}
			}
		});
		return () => {
			MediaStatus.removeRenderMediaStatusEventLinstener();
			AgentService.removeEventListener();
		};
	}, []);

	useEffect(() => {
		onScreenChange();
		// 渲染访客流
		largeStream().map(async (item: any) => {
			if (!item.id) return;

			if (AgentService.getRenderedStreamById(item.label)) {
				const stream = AgentService.getRenderedStreamById(item.label)?.stream;
				let video = document.getElementById(item.id) as HTMLVideoElement;
				video!.srcObject = stream as MediaProvider;

				video!.play();
				video && getAudioLevel(item.id, vol => setAudioLevel(vol));
				return;
			}
			const rederData = (await renderStream(item.label, item.id)) as { status: string; message: any };
			if (rederData.status === 'error') {
				setRenderErrorMessage(true);
			}

			let video = document.getElementById(item.id) as HTMLVideoElement;
			if (video) {
				const stream = video!.srcObject as MediaStream;
				AgentService.setRenderedStream(item.label, stream);
				getAudioLevel(item.id, vol => setAudioLevel(vol));
			}

			const defaultSperakerID = AgentService.getSpeakerDeviceID() ? AgentService.getSpeakerDeviceID() : AgentService.getDefaultSpeaker();

			if (defaultSperakerID) {
				await AgentService.switchSpeaker(item.id, defaultSperakerID);
			}
		});
		if (largeStream().length === 0) {
			setRenderErrorMessage(false);
		}

		setMediaStatus({ status: '', notGood: false });
		setCcsStatus({ status: '' });
		let video = new Video(largeStream()[0]?.id!);
		video.exitPictureInPicture(false);
	}, [largeStream()[0]?.id]);

	const checkIsFullScreen = () => {
		const isFullScreen = document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen;
		return isFullScreen == undefined ? false : isFullScreen;
	};

	const onFullscreenchange = () => {
		if (checkIsFullScreen()) {
			const list = [...tools];
			list.forEach((item: ToolPrpos) => {
				if (item.mode === 'scale') {
					item.isActive = true;
				}
			});
			setTools([...list]);
		} else {
			const list = [...tools];
			list.forEach((item: ToolPrpos) => {
				if (item.mode === 'scale') {
					item.isActive = false;
				}
			});
			setTools([...list]);
		}
	};

	const setPictureInPicture = (data: ToolPrpos) => {
		if (!largeStream()[0].id) return;
		const video = new Video(largeStream()[0].id!);
		const mode = data.isActive ? 'exit' : 'entry';
		if (mode === 'entry') {
			video.entryPictureInPicture();
		} else {
			video.exitPictureInPicture();
		}
	};

	// 截图
	const setScreenshot = (data: ToolPrpos) => {
		if (!largeStream()[0].id) {
			console.log('no video');
			return;
		}
		let clientId = largeStream()[0].clientId;
		let userName = largeStream()[0].userName;
		let taskKey = `${clientId}_${IBusinessName.SCREEN_SHOT}_${Math.floor(Math.random() * (999999999999 - 9 + 1)) + 9}`;
		BusinessTaskMap.addTask(taskKey, {
			name: IBusinessName.SCREEN_SHOT,
			clientId: clientId,
			status: IBusinessStatus.IN_PROGRESS,
			username: userName,
			userRole: AgentService.getSessionClientWithLabel(largeStream()[0].label)?.customerRole || '',
			cmdId: null
		});
		try {
			const video = document.getElementById(largeStream()[0].id!) as HTMLVideoElement;
			const stream = AgentService.getRenderedStreamById(largeStream()[0].label)?.stream as MediaProvider;
			let canvas = document.createElement('canvas');
			let track = stream.getVideoTracks()[0];
			const { height, width } = track.getSettings();
			canvas.height = height;
			canvas.width = width;
			canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
			let result = canvas.toDataURL('image/png');
			let fileName = Date.now() + 'screenshot' + '.png';
			let blob = dataURItoBlob(result);
			uploadFileWithBlob(blob, fileName)
				.then(async resp => {
					console.log('upload file', resp, resp.data.data);
					const { filename, size, url } = resp.data?.data;
					let responseData = {
						cmd: 'get-screenshot',
						data: {
							name: filename,
							size: size,
							url: url + `?token=${AgentService.getToken()}`
						},
						id: '',
						status: 'done'
					};
					let task = BusinessTaskMap.getTask(taskKey);
					setBusiness([
						{
							name: IBusinessName.SCREEN_SHOT,
							clientId: clientId,
							status: IBusinessStatus.DONE,
							username: userName,
							userRole: AgentService.getSessionClientWithLabel(largeStream()[0].label)?.customerRole || '',
							cmdId: null
						}
					]);
					BusinessTaskMap.addCompletedTask({ task: IBusinessName.SCREEN_SHOT, data: task!, response: responseData, isRead: false });
					BusinessTaskMap.delTask(taskKey); // 删除当前任务，防止邀请三方坐席，通知给其他坐席
					let messageData = {
						businessType: `save-screenshot`,
						url: resp.data?.data?.url
					};
					sendCustomeizeMessage(messageData, 'all');
				})
				.catch(error => {
					console.log(error, 'uploadFileWithBlob error');
					BusinessTaskMap.updateTaskStatus(clientId, IBusinessStatus.FAILED, null);
				});
		} catch (error) {
			let task = BusinessTaskMap.getTask(taskKey);
			setBusiness([
				{
					name: IBusinessName.SCREEN_SHOT,
					clientId: clientId,
					status: IBusinessStatus.FAILED,
					username: userName,
					userRole: AgentService.getSessionClientWithLabel(largeStream()[0].label)?.customerRole || '',
					cmdId: null
				}
			]);
			let responseData = {
				cmd: 'get-screenshot',
				data: {
					name: 'screenshot.png',
					size: 0,
					url: null
				},
				id: '',
				status: 'done'
			};
			BusinessTaskMap.addCompletedTask({ task: IBusinessName.SCREEN_SHOT, data: task!, response: responseData, isRead: false });
			BusinessTaskMap.delTask(taskKey); // 删除当前任务，防止邀请三方坐席，通知给其他坐席
		}
	};

	// 监听全屏或退出全屏
	const onScreenChange = () => {
		document.getElementById(`customer-stream-container`)!.addEventListener('fullscreenchange', function () {
			onFullscreenchange();
		});

		/* Firefox */
		document.getElementById(`customer-stream-container`)!.addEventListener('mozfullscreenchange', function () {
			onFullscreenchange();
		});

		/* Chrome, Safari 和 Opera */
		document.getElementById(`customer-stream-container`)!.addEventListener('webkitfullscreenchange', function () {
			onFullscreenchange();
		});

		/* IE / Edge */
		document.getElementById(`customer-stream-container`)!.addEventListener('msfullscreenchange', function () {
			onFullscreenchange();
		});
		document.getElementById(`customer-stream-container`)!.addEventListener('webkitbeginfullscreen', () => {
			const list = [...tools];
			list.forEach((item: ToolPrpos) => {
				if (item.mode === 'scale') {
					item.isActive = true;
				}
			});
			setTools([...list]);
		});
		document.getElementById(`customer-stream-container`)!.addEventListener('webkitendfullscreen', () => {
			const list = [...tools];
			list.forEach((item: ToolPrpos) => {
				if (item.mode === 'scale') {
					item.isActive = false;
				}
			});
			setTools([...list]);
		});
	};

	const setMute = async (data: ToolPrpos) => {
		const source = data.mode === 'play' ? 'video' : 'audio';
		const mode = data.isActive ? 'unmute' : 'mute';
		console.log('mute:', mode, source);
		try {
			const video: HTMLVideoElement = document.getElementById(largeStream()[0].id!) as HTMLVideoElement;
			video.volume = data.isActive ? 1 : 0;
			console.log(`${mode} customer ${source} success`);
			if (mode === 'mute') {
				// Message.normal(`${customerName}音量已关闭`);
			} else {
				// Message.normal(`${customerName}音量已开启`);
			}
		} catch (error) {
			console.log(error);
		}
	};

	useEffect(() => {
		console.log(largeStream(), 'largeStream()');
		if (!largeStream()[0]) return;
		const list = [...tools];
		list.forEach((item: ToolPrpos) => {
			if (item.mode === 'update') {
				item.isActive = largeStream()[0].streamMode === 'audio';
			}
		});
		setTools([...list]);
	}, [largeStream()]);

	const setScreenScale = (data: ToolPrpos) => {
		let ele = document.getElementById(`customer-stream-container`)!;
		if (fullscreenEnabled() && ele) {
			if (data.isActive) {
				cancelFullScreen();
			} else {
				const video = new Video(largeStream()[0].id!);
				video.exitPictureInPicture();
				launchFullScreen(ele);
			}
		}
	};
	const setUpdate = async (data: ToolPrpos) => {
		try {
			const mode = data.isActive ? 'video' : 'audio';
			const clientId = largeStream()[0]?.clientId || 'customer';
			const userName = largeStream()[0]?.userName || '';
			const role = 'customer';
			let messageData = {
				businessType: `request_media_upgrade`,
				mode,
				role,
				userName,
				clientId
			};
			const resp = await sendCustomeizeMessage(messageData, clientId);
			Message.normal(`${t('closed')}${t('client')}<${userName}>${t('video-picture')}`);

			console.log(resp);
		} catch (error) {
			console.log(error);
		}
	};

	const videoToolClick = (data: ToolPrpos) => {
		switch (data.mode) {
			case 'play':
				setMute(data);
				break;
			case 'unmute':
				setMute(data);
				break;
			case 'update':
				setUpdate(data);
				break;
			case 'scale':
				setScreenScale(data);
				break;
			case 'picture':
				setPictureInPicture(data);
				break;
			case 'screenshot':
				setScreenshot(data);
				break;
			// case 'mark':
			// 	streamMark(data);
			// 	break;
			default:
				break;
		}
		const list = [...tools];
		list.forEach((item: ToolPrpos) => {
			if (item.id === data.id) {
				item.isActive = !item.isActive;
			}
		});
		setTools([...list]);
	};

	const showAudioMedia = () => {
		return largeStream()[0]?.streamMode === 'audio';
	};

	const getCustomerStream = () => {
		return largeStream().length > 0;
	};

	useEffect(() => {
		// 处理远端ccs网络状态
		if (!largeStream()[0]) {
			return;
		}
		const items = networkStatus.remoteStatus.filter((item: any) => item.id === largeStream()[0].clientId);

		if (items && items.length > 0) {
			setCcsStatus({ status: items[0].status });
		}
	}, [networkStatus.remoteStatus]);

	useEffect(() => {
		if (!largeStream()[0]) {
			return;
		}
		// 处理远端ccs网络状态
		if (['reconnecting'].includes(ccsStatus.status)) {
			// 访客/坐席 <访客ID/坐席ID> 与服务端会话中断！
			Message.warning(t('client') + `<${largeStream()[0]?.userName}>` + t('session-disconnected') + '！');
		} else if (['resume-connect', 'connected'].includes(ccsStatus.status)) {
			// 访客/坐席 <访客ID/坐席ID> 与服务端重新连接成功！
			Message.normal(t('client') + `<${largeStream()[0]?.userName}>` + t('reconnected-success') + '！');
		}
	}, [ccsStatus.status]);

	const calculatorCustomerVideo = (layout: ILayout): string => {
		return resizeWin(AgentService.rootContainer).Width > 1199 ? `pc-layout-${layout}-customer-video customer-stream-container` : `pad-layout-${layout}-customer-video customer-stream-container`;
	};
	const calculatorCustomerVideoWrapper = (layout: ILayout): string => {
		return resizeWin(AgentService.rootContainer).Width > 1199
			? `pc-layout-${layout}-customer-video-wrapper customer-stream-container`
			: `pad-layout-${layout}-customer-video-wrapper customer-stream-container`;
	};

	const renderView = useMemo(() => {
		if (largeStream().length === 0) {
			return (
				<>
					<span className="video-desc" style={{ fontSize: '14px' }}>
						{t('no-calls')}
					</span>
				</>
			);
		}
		const client = AgentService.getSessionClientWithLabel(largeStream()[0].label);

		console.log('getSessionClientWithLabel', client);
		if (client?.status === 'permission' || client?.status === 'publish' || client?.status === 'idle' || client?.status === 'joining') {
			return (
				<>
					{client.userName ? <DescMask desc={t('client') + `<${client.userName}>`} /> : undefined}
					{client.customerRole ? <span className="customer-role">{client.customerRole}</span> : undefined}
					<AuthorizationTips status={AgentService.getSessionClientWithLabel(largeStream()[0].label)?.status || 'idle'} />
				</>
			);
		}
		if (client?.status === 'published') {
			return (
				<>
					{client.userName ? <DescMask desc={t('client') + `<${client.userName}>`} /> : undefined}
					{client.customerRole ? <span className="customer-role">{client.customerRole}</span> : undefined}
					<LargeVideoWrapper className="customer-large-video-wrapper" style={{ height: '100%' }}>
						<video playsInline controls autoPlay id={largeStream()[0].id || 'customer-large-container'} className="customervideo"></video>
					</LargeVideoWrapper>
				</>
			);
		}
	}, [largeStream(), t('no-calls')]);

	const NetWorkGood = (
		<NetWork>
			<img src={require('../../assets/img/netWork-good.png')} alt="" width={20} height={16} />
		</NetWork>
	);

	const NetWorkNotGood = (
		<NetWork>
			<img src={require('../../assets/img/newWork-notGod.png')} alt="" width={20} height={16} />
		</NetWork>
	);

	const NetWorkFailed = (
		<NetWork>
			<img src={require('../../assets/img/netWork-failed.png')} alt="" width={20} height={16} />
		</NetWork>
	);

	const getNetWork = () => {
		if (['connecting', 'failed', 'disconnected'].includes(mediaStatus.status)) {
			return NetWorkFailed;
		} else if (mediaStatus.notGood) {
			return NetWorkNotGood;
		} else {
			return NetWorkGood;
		}
	};

	const getVideoTool = (tools: ToolPrpos[]) => {
		// console.log('tools', tools);
		const list = [...tools];
		if ((callMediaType === 'audio' || showAudioMedia()) && largeStream().length !== 0) {
			return list.filter(item => item.mode !== 'update' && item.mode !== 'screenshot' && item.mode !== 'picture');
		}
		return list;
	};

	const streamMark = async (data: ToolPrpos) => {
		console.log('stream mark', data, largeStream());
		try {
			const clientId = largeStream()[0]?.clientId || 'customer';
			const userName = largeStream()[0]?.userName || '';
			const role = 'customer';
			let messageData = {
				businessType: `start-video-mark`,
				role,
				userName,
				clientId
			};
			await sendCustomeizeMessage(messageData, clientId);
			// createCustomerStreamContainer({
			// 	stopMark: stopMark,
			// 	clientId: largeStream()[0].clientId,
			// 	videoId: largeStream()[0].id // 访客流原始videoId
			// });
		} catch (error) {
			console.log('start-video-mark error', error);
			Message.normal(`${t('operation-failed')}`);
		}
	};

	// 结束标注
	const stopMark = async (clientId: string) => {
		console.log('stopMark clientId', clientId);
		try {
			const clientId = largeStream()[0]?.clientId || 'customer';
			const userName = largeStream()[0]?.userName || '';
			const role = 'customer';
			let messageData = {
				businessType: `stop-video-mark`,
				role,
				userName,
				clientId
			};
			await sendCustomeizeMessage(messageData, clientId);
		} catch (error) {
			console.log('stop-video-mark error', error);
			Message.normal(`${t('operation-failed')}`);
		}
	};

	return (
		<>
			<div className={calculatorCustomerVideoWrapper(layout as ILayout)} style={{ height: height }} id="customer-subtitle-warpper">
				<div className={calculatorCustomerVideo(layout as ILayout)} id="customer-stream-container">
					{getBusiness()?.status === IBusinessStatus.IN_PROGRESS || getBusiness()?.status === IBusinessStatus.START || getBusiness()?.status === IBusinessStatus.ACCEPTED ? (
						<Instructions businessData={getBusiness()} />
					) : undefined}

					{renderView}
					{/* {getCustomerStream() ? (
						<LargeVideoWrapper className="customer-large-video-wrapper" style={{ height: '100%' }}>
							<video playsInline controls autoPlay id={largeStream()[0].id || 'customer-large-container'} className="customervideo"></video>
						</LargeVideoWrapper>
					) : (
						<span className="video-desc" style={{ fontSize: '14px' }}>
							{t('no-calls')}
						</span>
					)} */}

					{callMediaType === 'audio' && largeStream().length !== 0 ? (
						<audio className="customer_video_hidden" playsInline controls autoPlay id="customer_voice" muted={false}></audio>
					) : undefined}
					{(callMediaType === 'audio' || showAudioMedia()) && largeStream().length !== 0 ? <AudioMedia classname="audio" audioLevel={audioLevel()}></AudioMedia> : undefined}
					{getCustomerStream() ? <VideoTool tools={getVideoTool(tools)} classname="widget-video-tool-container" onclick={videoToolClick}></VideoTool> : undefined}
					<CustomerCanvas id={getCustomerStream() ? largeStream()[0].id : ''} />
					{/* failed'|'connecting'|'connected'|'disconnected'|'quality-report */}
					{getCustomerStream() ? getNetWork() : null}
					{['reconnecting'].includes(ccsStatus.status) ? (
						<div className="render-media-status">
							<span className="label">{t('session-broken')}，</span>
							<span className="label">
								{t('try-connnecting')}
								<InstructionsSpan>...</InstructionsSpan>
							</span>
						</div>
					) : null}
				</div>
				{renderErrorMessage() ? <RenderErrorMessage>{t('playback-stream-error')}</RenderErrorMessage> : undefined}
			</div>
		</>
	);
};

export default CustomerStream;
